using UnityEngine;
using System.Collections;


public class Mover : MoverBase {
	
	
	protected Quaternion alignCorrection;
	
	//IOS Control
	public float touchControlAccel = 1.0f;
	public float touchControlRange = 100.0f;
	protected Vector2 beginPressedPos;
	protected Vector2 offset;
	
	
	
	protected bool isLeftTouched;
	protected bool isRightTouched;
	
	// Use this for initialization 
	void Awake()
	{
		
		alignCorrection = new Quaternion();
		alignCorrection.SetLookRotation(forwardVector, Vector3.up);
		alignCorrection = Quaternion.Inverse(alignCorrection);
		
		
		
	}
	
	public int jumpCount{
		get{return _jumpCount;}
	}
	public Vector3 desiredFacingDirection {
		get { return _faceDirection; }
		set {
			_faceDirection = value;
			if (_faceDirection.magnitude > 1)
				_faceDirection = _faceDirection.normalized;
		}
	}
	public Vector3 desiredMovementDirection {
		
		get { 
			if (_movement.magnitude>1) _moveDirection = _movement.normalized;
			return _moveDirection;
		}
		
	}
	protected void Update ()
	{
		if(customUpdateAnimationFunction == null)	customUpdateAnimationFunction = updateAnimation;
		if(customUpdateMoveFunction == null)	customUpdateMoveFunction = updateMove;
		
		customUpdateAnimationFunction();
		
		// if move left/right
		if(customUpdateMoveFunction(this))
			UpdateFacingDirection ();
		
		
	}
	
	public void Jump()
	{
		if(jumpCount < maxJumpCount)
		{
			state.animState = AnimationState.Jump;
			CharacterController controller = GetComponent<CharacterController> ();
		
			_movement.y = jumpSpeed;
	
			controller.Move (new Vector3(0,jumpSpeed,0) * Time.deltaTime);
			_jumpCount++;
		}
		
		
	}
	protected override bool updateMove (MoverBase mb)
	{
		if(UtilEx.isIOS())
		{
			return UpdateMoveIOS();
		}
		CharacterController controller = GetComponent<CharacterController> ();
		
		verticalOffset = Input.GetAxis ("Vertical");
		horizontalOffset = Input.GetAxis ("Horizontal");
		
		if (controller.isGrounded) {
			
			//reset JumpCount
			_jumpCount = 0;
			
			//get Direction from controller (Keyboard)
			desiredFacingDirection = new Vector3 (horizontalOffset, 0, verticalOffset);
			
			_movement = transform.TransformDirection (desiredFacingDirection);
			
			
			
			
			
			_movement *= speed;
			
			if (Input.GetButton ("Jump"))
				Jump();
			
		}
		
		
		//apply gravity
		_movement.y -= gravity * Time.deltaTime;
		controller.Move (_movement * Time.deltaTime);
		
		//return ture when it is moving
		return Mathf.Abs(horizontalOffset) > 0;
		
	}
	
	protected override bool updateAnimation()
	{
		if(state == null)
		{
			state = GetComponent<ActorController>().actorState;
		}
		
		state.animState = _movement.magnitude < walkIdleThreshold ? AnimationState.Idle : AnimationState.Walk;
		//print(_movement.magnitude);
		return true;
	}
	 protected bool UpdateMoveIOS ()
	{
		
		CharacterController controller = GetComponent<CharacterController> ();
		//apply gravity
		if(!controller.isGrounded)
		{
			//reset JumpCount
			
			_movement.y -= gravity * Time.deltaTime; 
		}else
		{
			_jumpCount = 0;
		}
		
		//apply movment
		controller.Move (_movement * Time.deltaTime);
		
		
		
		bool returnVal = false;
		
		//loop all touch event and serperate to onLeft/Right
		foreach(Touch evt in Input.touches)
		{
			if(evt.position.x < Screen.width / 2)
			{
				isLeftTouched = true;
				//if last time is touching right
				if(isRightTouched && Input.touchCount == 1)
				{
					onCrossHalfScreen(false);
					isRightTouched = false;
				}
				
				returnVal = onLeftPanelTouched(evt);
				
			}else
			{
				isRightTouched = true;
				//if last time is touching left
				
				if(isLeftTouched && Input.touchCount == 1)
				{
					onCrossHalfScreen(true);
					isLeftTouched = false;
				}
					
				
				returnVal = onRightPanelTouched(evt);
			}
		}
		
		if(!returnVal)
		{
			state.animState = AnimationState.Idle;
		}
		
		return returnVal;
		
	}
	void onCrossHalfScreen(bool fromLeftToRight)
	{
		if(fromLeftToRight)
		{
			stopPlayer();
		}
	}
	bool onLeftPanelTouched(Touch evt)
	{
		if(evt.phase == TouchPhase.Began)
		{	
			beginPressedPos = evt.position;
			state.animState = AnimationState.Walk;
					
		}else if(evt.phase == TouchPhase.Moved || evt.phase == TouchPhase.Stationary)
		{
					
			offset = evt.position - beginPressedPos;
			CharacterController controller = GetComponent<CharacterController> ();
		
			if(controller.isGrounded)
			{
				//direction from player to camera's position (x,0,z)
				Vector3 camProjForward = Util.ProjectOntoPlane(Camera.current.transform.rotation * Vector3.forward,Vector3.up);
				
				Quaternion camRot = Quaternion.LookRotation(camProjForward);
			
				//create a rotation from 2D input to camera look direction.
				desiredFacingDirection = camRot * (new Vector3 (offset.x, 0,offset.y));
				
				_movement =  desiredFacingDirection;
				
				
				
				//apply speed
				_movement *= speed * (offset.magnitude / touchControlRange * touchControlAccel);
				
			}
			
			
		}else // touch end
		{
			stopPlayer();
		}
	
		return true;
	
		
	}
	void stopPlayer()
	{
		_movement.x = 0;
		_movement.z = 0;
			
		state.animState = AnimationState.Idle;
	}
	
	bool onRightPanelTouched(Touch evt)
	{
		//	print("costLeven:" + Levenshetin.Compute("12111111111","56").ToString()); //OK
		//
		//		switch(evt.phase)
		//		{
		//			case TouchPhase.Began:
		//				leven.onCatureStart(evt);
		//				break;
		//			case TouchPhase.Moved:
		//				leven.onGestureCapturing(evt);
		//				break;
		//			case TouchPhase.Ended:
		//				leven.onCatpureEnd(evt);
		//				//print(leven.lastGesture);			//OK 
		//				break;
		//		}
		return true;
	}
	
	virtual protected void UpdateFacingDirection ()
	{
		if(UtilEx.isIOS())
		{
			CharacterController controller = GetComponent<CharacterController> ();
		
			if(desiredFacingDirection.magnitude > 0)
				controller.transform.rotation = Quaternion.Slerp(controller.transform.rotation,Quaternion.LookRotation(desiredFacingDirection),Time.deltaTime*10);
		}else{
		
			// Calculate which way character should be facing
			Vector3 combinedFacingDirection = transform.rotation * desiredFacingDirection;
			combinedFacingDirection = Util.ProjectOntoPlane (combinedFacingDirection, transform.up);
			combinedFacingDirection = alignCorrection * combinedFacingDirection;
		
			if (combinedFacingDirection.sqrMagnitude > 0.1f) {
				Vector3 newForward = Util.ConstantSlerp (transform.forward, combinedFacingDirection, maxRotationSpeed * Time.deltaTime);
				newForward = Util.ProjectOntoPlane (newForward, transform.up);
				//Debug.DrawLine(transform.position, transform.position+newForward, Color.yellow);
				Quaternion q = new Quaternion ();
				q.SetLookRotation (newForward, transform.up);
				transform.rotation = q;
			}
		}
	}
}
